/*
    Copyright 2010 Northbranchlogic, Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

package com.norbl.runjrun;

import com.norbl.runjrun.exception.*;
import com.norbl.util.*;

/** Contains all parameters needed to run a {@link RunnerNode} on
 *  an EC2 instance.
 *
 * @author Barnet Wagman
 */
public class NodeParams extends AbstractParams {

    String awsAccessID;
    String awsSecretKey;

    String jarBucketName;
    String jarS3KeyPrefix;

    String appDirPath;
    String jarDirPath;

    String taskQueueName;
   
    String exceptionBucketName;
    String exceptionS3KeyPrefix;

    Long emptyQueueNapMillis;
    Long maxMissingTaskMillis;

    Long s3RetryMillis;
    Long s3MaxWaitMillis;

    Long sdbRetryMillis;
    Long sdbMaxWaitMillis;

    Long cleanIntervalMillis;
    Long pulseIntervalMillis;

    Integer maxHeapGb;
    String jvmParams;

    public NodeParams(String awsAccessID,String awsSecretKey,
                      String jarBucketName, String jarS3KeyPrefix,
                      String appDirPath, String jarDirPath,
                      String taskQueueName,
                      String exceptionBucketName,
                      String exceptionS3KeyPrefix,
                      Long emptyQueueNapMillis,
                      Long maxMissingTaskMillis,
                      Long s3RetryMillis,
                      Long s3MaxWaitMillis,
                      Long sdbRetryMillis,
                      Long sdbMaxWaitMillis,
                      Long cleanIntervalMillis,
                      Long pulseIntervalMillis,
                      Integer maxHeapGb,
                      String jvmParams) {

        this.awsAccessID = awsAccessID;
        this.awsSecretKey = awsSecretKey;

        this.jarBucketName = jarBucketName;
        this.jarS3KeyPrefix = jarS3KeyPrefix;

        this.appDirPath = appDirPath;
        this.jarDirPath = jarDirPath;

        this.taskQueueName = taskQueueName;

        this.exceptionBucketName = exceptionBucketName;
        this.exceptionS3KeyPrefix = exceptionS3KeyPrefix;
        
        this.emptyQueueNapMillis = emptyQueueNapMillis;
        this.maxMissingTaskMillis = maxMissingTaskMillis;

        this.s3RetryMillis = s3RetryMillis;
        this.s3MaxWaitMillis = s3MaxWaitMillis;

        this.sdbRetryMillis = sdbRetryMillis;
        this.sdbMaxWaitMillis = sdbMaxWaitMillis;

        this.cleanIntervalMillis = cleanIntervalMillis;
        this.pulseIntervalMillis = pulseIntervalMillis;

        this.maxHeapGb = maxHeapGb;
        this.jvmParams = jvmParams;

        checkForRequiredParams();
    }

    public NodeParams(String message) {
        setParams(message,this.getClass().getDeclaredFields(),true);

            // Set missing params to defaults if possible.
        if ( jarS3KeyPrefix == null )
            jarS3KeyPrefix = Constants.JAR_S3_KEY_PREFIX_DEFAULT;
        if ( appDirPath == null ) appDirPath = Constants.APP_DIR_PATH_DEFAULT;
        if ( jarDirPath == null ) jarDirPath = Constants.JAR_DIR_PATH_DEFAULT;
        if ( taskQueueName == null ) taskQueueName = Constants.TASKQUEUE_NAME_DEFAULT;
        if ( exceptionS3KeyPrefix == null )
            exceptionS3KeyPrefix = Constants.EXCEPTION_S3_KEY_PREFIX_DEFAULT;
        if ( emptyQueueNapMillis == null )
            emptyQueueNapMillis = Constants.EMPTY_QUEUE_NAP_MILLIS_DEFAULT;
        if ( maxMissingTaskMillis == null ) 
            maxMissingTaskMillis = Constants.MAX_MISSING_TASK_MILLIS_DEFAULT;
        if ( s3RetryMillis == null )
            s3RetryMillis = Constants.S3_RETRY_INTERVAL_MILLIS_DEFAULT;
        if ( s3MaxWaitMillis == null )
            s3MaxWaitMillis = Constants.S3_MAX_WAIT_MILLIS_DEFAULT;
        if ( sdbRetryMillis == null )
            sdbRetryMillis = Constants.SDB_RETRY_INTERVL_MILLIS_DEFAULT;
        if ( sdbMaxWaitMillis == null )
            sdbMaxWaitMillis = Constants.SDB_MAX_WAIT_MILLIS_DEFAULT;
        if ( maxHeapGb == null ) maxHeapGb = new Integer(0);
        if ( jvmParams == null ) jvmParams = "";


        checkForRequiredParams();
    }

    protected void checkForRequiredParams() {

        String m = "";
        if ( awsAccessID == null ) m += "awsAccessID ";
        if ( awsSecretKey == null ) m += "awsSecretKey ";
        if ( jarBucketName == null ) m += "jarBucketName ";
        if ( jarS3KeyPrefix == null ) m += "jarS3KeyPrefix ";
        if ( appDirPath == null ) m += "appDirPath ";
        if ( jarDirPath == null ) m += "jarDirPath ";
        if ( taskQueueName == null ) m+= "taskQueueName ";
        if ( exceptionBucketName == null ) m += "exceptionBucketName ";
        if ( exceptionS3KeyPrefix == null ) m += "exceptionS3KeyPrefix ";
        if ( emptyQueueNapMillis == null ) m += "emptyQueueNapMillis ";
        if ( maxMissingTaskMillis == null ) m += "maxMissingTaskMillis ";
        if ( s3RetryMillis == null ) m += "s3RetryMillis ";
        if ( s3MaxWaitMillis == null ) m += "s3MaxWaitMillis ";
        if ( sdbRetryMillis == null ) m += "sdbRetryMillis ";
        if ( sdbMaxWaitMillis == null ) m += "sdbMaxWaitMillis";
        if ( cleanIntervalMillis == null ) m += "cleanIntervalMillis ";
        if ( pulseIntervalMillis == null ) m += "pulseIntervalMillis ";
        if ( maxHeapGb == null ) m += "maxHeapGb";
        if ( jvmParams == null ) m += "jvmParams";

        m = m.trim();
        if ( m.length() >= 1 ) {
            throw new MissingParameterException("The following required " +
                "parameters are missing: " + m);
        }
    }


    public String toMessageString() {
        return( toMessageString(this.getClass().getDeclaredFields()) );
    }

    public static NodeParams createDefault(String awsAccessKey,
                                           String awsSecretKey,
                                           String bucketName,
                                           int maxHeapGb) {
        return( new NodeParams(awsAccessKey,awsSecretKey,
                               bucketName, // Jar bucket name
                               Constants.JAR_S3_KEY_PREFIX_DEFAULT,
                               Constants.APP_DIR_PATH_DEFAULT,
                               Constants.JAR_DIR_PATH_DEFAULT,
                               Constants.TASKQUEUE_NAME_DEFAULT,
                               bucketName,
                               Constants.EXCEPTION_S3_KEY_PREFIX_DEFAULT,
                               Constants.EMPTY_QUEUE_NAP_MILLIS_DEFAULT,
                               Constants.MAX_MISSING_TASK_MILLIS_DEFAULT,
                               Constants.S3_RETRY_INTERVAL_MILLIS_DEFAULT,
                               Constants.S3_MAX_WAIT_MILLIS_DEFAULT,
                               Constants.SDB_RETRY_INTERVL_MILLIS_DEFAULT,
                               Constants.SDB_MAX_WAIT_MILLIS_DEFAULT,
                               Constants.CLEAN_INTERVAL_MILLIS_DEFAULT,
                               Constants.PULSE_INTER_MILLIS_DEFAULT,
                               new Integer(maxHeapGb),
                               Constants.NODE_JVM_PARAMS_DEFAULT
                               ) );
    }


        /** main() writes default params as a message string to the stdout.
         *  args:
         *  <blockquote>
         *      awsAccessKeyID=<br>
         *      awsSecretKey=<br>
         *      bucketName=
         *  </blockquote>
         *      
         *
         * @param argv
         */
    public static void main(String[] argv) {

        if ( argv.length != 3 ) {
            System.out.println(getUsage());
            return;
        }
       
        PropertyList pl = new PropertyList();
        for ( String arg : argv ) {
            pl.add(Property.parsePair(arg));
        }
                
        String awsAccessID = (String) pl.getPropertyValue("awsAccessID");
        String awsSecretKey = (String) pl.getPropertyValue("awsSecretKey");
        String bucketName = (String) pl.getPropertyValue("bucketName");
        
        if( (awsAccessID == null) || (awsSecretKey == null) ||
            (bucketName == null) ) {
            System.out.println(getUsage());
            return;
        }

        System.out.println(
            NodeParams.createDefault(awsAccessID, awsSecretKey,
                                     bucketName,
                                     Constants.NODE_MAX_HEAP_GB_DEFAULT
                                     ).toMessageString() );
    }

    private static String getUsage() {
        return("Usage: java ... com.norbl.NodeParams " +
                                "awsAccessID=<access key> " +
                                "awsSecretKey=<secret key> " +
                                "bucketName=<bucket name>");
    }
}
